#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
文件: aggregated_api.py
说明: 小程序聚合/页面级接口真实实现 (方案C - 一次到位归一化)

保留聚合价值端点:
  /records/statistics  /records
  /user/security-status
  /export/history       /export

不再保留的聚合:
  /followup* 已弃用 => 直接使用实体端点 /api/followup_records/* (前端将切换)

设计原则:
1. 聚合只做“跨实体合并 + 基本统计 + 轻量格式化”，不复制复杂业务逻辑。
2. 数据来源直接查询实体模型 (VisionRecord / InterventionRecord / SocialShare / User)。
3. 分页策略: /records 统一 page+limit，按事件时间倒序(vision: measure_date, intervention: intervention_date)。
4. 性能: 先简单两次查询合并。数据量扩大后可用 UNION ALL + 原生SQL 或视图优化。
5. 导出: 暂无独立任务表，记录写入统一日志服务 (后续可引入 export_tasks 表)。
6. 归一化: 去掉占位返回，全量真实字段；文档同步更新由脚本/人工完成。
"""

from datetime import datetime
from flask import request, jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity
from backend.api.miniprogram import miniprogram_bp
from backend.infrastructure.database import db
from backend.models.user import User
from backend.models.vision import VisionRecord
from backend.models.intervention import InterventionRecord
from backend.models.social_share import SocialShare
from backend.models.medical_consult import MedicalConsult
from backend.services.unified_log_service import UnifiedLogService

log_service = UnifiedLogService()

# =============== 用户安全状态 ===============
@miniprogram_bp.route('/user/security-status', methods=['GET'])
@jwt_required()
def security_status():
    """返回用户安全状态真实信息"""
    try:
        uid = int(get_jwt_identity())
        user = User.query.get(uid)
        if not user:
            return jsonify({'code': 404, 'message': '用户不存在'}), 404
        data = {
            'hasPassword': bool(user.password_hash),
            'hasPhone': bool(user.mobile),
            'loginDevices': 1,  # 设备管理后续扩展
            'lastLoginTime': user.last_login.isoformat() + 'Z' if user.last_login else None
        }
        return jsonify({'code': 0, 'data': data})
    except Exception as e:
        return jsonify({'code': 500, 'message': f'获取安全状态失败: {str(e)}'}), 500

# =============== 记录统计 ===============
@miniprogram_bp.route('/records/statistics', methods=['GET'])
@jwt_required()
def records_statistics():
    """汇总 vision + intervention + social + doctor 计数"""
    try:
        uid = int(get_jwt_identity())
        user = User.query.get(uid)
        if not user or not user.student_id:
            stats = { 'totalRecords': 0, 'visionRecords': 0, 'interventionRecords': 0, 'socialRecords': 0, 'doctorRecords': 0 }
            return jsonify({'code': 0, 'data': stats})
        sid = user.student_id
        vision_count = db.session.query(VisionRecord.id).filter(VisionRecord.student_id == sid).count()
        intervention_count = db.session.query(InterventionRecord.id).filter(InterventionRecord.student_id == sid).count()
        social_count = db.session.query(SocialShare.id).filter(SocialShare.student_id == sid).count()
        # 医生交流记录可能通过user_id或student_id关联
        doctor_count = db.session.query(MedicalConsult.id).filter(
            (MedicalConsult.student_id == sid) | (MedicalConsult.user_id == uid)
        ).count()
        stats = {
            'totalRecords': vision_count + intervention_count + social_count + doctor_count,
            'visionRecords': vision_count,
            'interventionRecords': intervention_count,
            'socialRecords': social_count,
            'doctorRecords': doctor_count
        }
        return jsonify({'code': 0, 'data': stats})
    except Exception as e:
        return jsonify({'code': 500, 'message': f'获取记录统计失败: {str(e)}'}), 500

@miniprogram_bp.route('/records', methods=['GET'])
@jwt_required()
def records_list():
    """聚合 vision + intervention + social + doctor 按时间倒序分页"""
    try:
        uid = int(get_jwt_identity())
        user = User.query.get(uid)
        if not user or not user.student_id:
            return jsonify({'code': 0, 'data': {'records': [], 'page': 1, 'limit': 20}})
        sid = user.student_id
        page = int(request.args.get('page', 1))
        limit = int(request.args.get('limit', 20))
        type_filter = request.args.get('type', 'all')  # all / vision / intervention / social / doctor
        date_range = request.args.get('dateRange', '30d')

        from datetime import timedelta, date
        date_threshold = None
        today = date.today()
        if date_range == '7d':
            date_threshold = today - timedelta(days=7)
        elif date_range == '30d':
            date_threshold = today - timedelta(days=30)
        elif date_range == '90d':
            date_threshold = today - timedelta(days=90)
        # 'all' -> 不限制

        vision_q = VisionRecord.query.filter(VisionRecord.student_id == sid)
        intervention_q = InterventionRecord.query.filter(InterventionRecord.student_id == sid)
        social_q = SocialShare.query.filter(SocialShare.student_id == sid)
        # 医生交流记录可能通过user_id或student_id关联
        doctor_q = MedicalConsult.query.filter(
            (MedicalConsult.student_id == sid) | (MedicalConsult.user_id == uid)
        )
        
        if date_threshold:
            vision_q = vision_q.filter(VisionRecord.measure_date >= date_threshold)
            intervention_q = intervention_q.filter(InterventionRecord.intervention_date >= date_threshold)
            social_q = social_q.filter(SocialShare.created_at >= datetime.combine(date_threshold, datetime.min.time()))
            doctor_q = doctor_q.filter(MedicalConsult.created_at >= datetime.combine(date_threshold, datetime.min.time()))

        # 只在需要的类型上查询，减少无用数据
        records = []
        if type_filter in ('all', 'vision'):
            for vr in vision_q.order_by(VisionRecord.measure_date.desc()).limit(limit*3):
                records.append({
                    'id': vr.id,
                    'type': 'vision',
                    'date': vr.measure_date.isoformat(),
                    'created_at': vr.created_at.isoformat() if vr.created_at else None,
                    'summary': {
                        'left_eye_naked': vr.left_eye_naked,
                        'right_eye_naked': vr.right_eye_naked,
                        'left_sphere': vr.left_sphere,
                        'right_sphere': vr.right_sphere,
                        'is_baseline': vr.is_baseline
                    }
                })
        if type_filter in ('all', 'intervention'):
            for ir in intervention_q.order_by(InterventionRecord.intervention_date.desc()).limit(limit*3):
                records.append({
                    'id': ir.id,
                    'type': 'intervention',
                    'date': ir.intervention_date.isoformat(),
                    'created_at': ir.created_at.isoformat() if ir.created_at else None,
                    'summary': {
                        'intervention_type': ir.intervention_type,
                        'immediate_effect': ir.immediate_effect,
                        'cooperation_level': ir.cooperation_level
                    }
                })
        if type_filter in ('all', 'social'):
            for sr in social_q.order_by(SocialShare.created_at.desc()).limit(limit*3):
                records.append({
                    'id': sr.id,
                    'type': 'social',
                    'date': sr.created_at.date().isoformat(),
                    'created_at': sr.created_at.isoformat(),
                    'summary': {
                        'title': sr.title,
                        'like_count': sr.like_count or 0,
                        'comment_count': sr.comment_count or 0,
                        'image_count': len(sr.images) if sr.images else 0
                    }
                })
        if type_filter in ('all', 'doctor'):
            for dr in doctor_q.order_by(MedicalConsult.created_at.desc()).limit(limit*3):
                records.append({
                    'id': dr.id,
                    'type': 'doctor',
                    'date': dr.created_at.date().isoformat(),
                    'created_at': dr.created_at.isoformat(),
                    'summary': {
                        'title': dr.title,
                        'status': 'replied' if dr.replied_at else 'pending',
                        'replied_at': dr.replied_at.isoformat() if dr.replied_at else None
                    }
                })

        # 聚合排序（按 date + created_at 降序）
        records.sort(key=lambda r: (r['date'], r['created_at'] or r['date']), reverse=True)

        # 简单分页切片
        start = (page - 1) * limit
        end = start + limit
        page_slice = records[start:end]

        return jsonify({'code': 0, 'data': {'records': page_slice, 'page': page, 'limit': limit}})
    except Exception as e:
        return jsonify({'code': 500, 'message': f'获取记录失败: {str(e)}'}), 500

# =============== 导出 (轻量占位真实) ===============
@miniprogram_bp.route('/export/history', methods=['GET'])
@jwt_required()
def export_history():
    """导出历史：当前阶段尚无持久化任务表 -> 返回空数组"""
    return jsonify({'code': 0, 'data': []})

@miniprogram_bp.route('/export', methods=['POST'])
@jwt_required()
def export_data():
    """执行导出: 记录操作日志，返回伪任务信息 (后续可扩展生成文件)"""
    try:
        uid = int(get_jwt_identity())
        payload = request.get_json() or {}
        try:
            log_service.log_operation(
                user_id=uid,
                action='EXPORT_DATA',
                table_name='(aggregated)',
                record_id=None,
                details=f"导出参数: {payload}"[:400]
            )
        except Exception:
            pass
        result = {
            'taskId': f'export-{int(datetime.utcnow().timestamp())}',
            'fileName': 'export_result_placeholder.xlsx',
            'downloadUrl': ''  # 暂无真实文件
        }
        return jsonify({'code': 0, 'data': result, 'message': '导出任务已记录（后续生成真实文件）'})
    except Exception as e:
        return jsonify({'code': 500, 'message': f'导出失败: {str(e)}'}), 500

# =============== 自检端点 (可保留) ===============
@miniprogram_bp.route('/__aggregated/status', methods=['GET'])
def aggregated_status():
    return jsonify({
        'success': True,
        'data': {
            'endpoints': ['/user/security-status', '/records/statistics', '/records', '/export/history', '/export'],
            'deprecated': ['/followup/*'],
            'note': '聚合层已实现真实逻辑；随访聚合弃用，使用 /api/followup_records/*'
        }
    })
